<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Steering Behaviours: SEEK</title>

    <script src="../libs/dat.gui.min.js"></script>
    <script src="../libs/stats.min.js"></script>
    <script src="../libs/three.min.js"></script>
    <script src="../js/threejs/controls/OrbitControls.js"></script>
    <script src="../js/ThreeSteer.js"></script>
    <link rel="stylesheet" type="text/css" href="css/main.css" />
    <link rel="stylesheet" type="text/css" href="css/gui.css" />
  </head>
  <script>
    var container;
    var camera;

    var scene, renderer;
    var controls;
    var stats;
    var entity;
    var ball;
    var boundaries;
    var entities;
    var params;

    function init(element) {
      container = document.getElementById(element);
      camera = new THREE.PerspectiveCamera(
        45,
        window.innerWidth / window.innerHeight,
        1,
        50000
      );
      scene = new THREE.Scene();

      renderer = new THREE.WebGLRenderer({ alpha: true });
      renderer.setClearColor(0x333333, 0);
      renderer.setSize(window.innerWidth, window.innerHeight);
      renderer.domElement.style.position = "absolute";
      renderer.domElement.style.top = 0;
      container.appendChild(renderer.domElement);

      camera.position.set(0, 10000, 10000);
      camera.lookAt(new THREE.Vector3(0, 0, 0));

      controls = new THREE.OrbitControls(camera, renderer.domElement);
      controls.maxPolarAngle = Math.PI * 0.5;
      controls.minDistance = 100;
      controls.maxDistance = 30000;

      stats = new Stats();
      stats.domElement.style.position = "absolute";
      stats.domElement.style.bottom = "0px";
      stats.domElement.style.left = "180px";
      stats.domElement.style.zIndex = 100;
      container.appendChild(stats.domElement);

      // Floor
      var floorGeometry = new THREE.PlaneGeometry(10000, 10000, 32);
      var floorMaterial = new THREE.MeshBasicMaterial({
        color: 0x666666,
        transparent: true,
        opacity: 0.5,
      });
      var floor = new THREE.Mesh(floorGeometry, floorMaterial);
      floor.rotation.x = -Math.PI * 0.5;
      scene.add(floor);

      params = {
        inSightDistance: 1000,
        tooCloseDistance: 400,
        maxSpeed: 15,
        maxForce: 5,
        lookAtDirection: true,
        numEntities: 20,
      };

      // Entity Mesh
      var geometry = new THREE.BoxGeometry(100, 200, 50);
      var material = new THREE.MeshBasicMaterial({
        color: 0xffffff,
        wireframe: true,
      });

      // Entities
      entities = [];
      for (var i = 0; i < params.numEntities; i++) {
        var mesh = new THREE.Mesh(geometry, material);
        mesh.position.setY(100);
        var entity = new SteeringEntity(i, mesh);
        entity.position.set(
          Math.random() * (2500 - -2500) + -2500,
          0,
          Math.random() * (2500 - -2500) + -2500
        );
        entity.velocity.set(
          Math.random() * 20 - 10,
          0,
          Math.random() * 20 - 10
        );
        entities.push(entity);
        scene.add(entity);
      }

      //Plane boundaries (do not cross)
      boundaries = new THREE.Box3(
        new THREE.Vector3(-5000, 0, -5000),
        new THREE.Vector3(5000, 0, 5000)
      );

      //Gui

      var gui = new dat.GUI();
      var quantity = gui
        .add(params, "numEntities", 2, 100)
        .name("Num Of Entities")
        .step(1);
      quantity.onFinishChange(function (value) {
        for (var i = 0; i < entities.length; i++) {
          scene.remove(entities[i]);
          entities[i].mesh.geometry.dispose();
          entities[i].mesh.material.dispose();
        }

        entities = [];

        for (var i = 0; i < value; i++) {
          var mesh = new THREE.Mesh(geometry, material);
          mesh.position.setY(200);
          var entity = new SteeringEntity(i, mesh);
          entity.position.set(
            Math.random() * (2500 - -2500) + -2500,
            0,
            Math.random() * (2500 - -2500) + -2500
          );
          entity.velocity.set(
            Math.random() * 20 - 10,
            0,
            Math.random() * 20 - 10
          );
          entities.push(entity);
          scene.add(entity);
        }
      });

      gui.add(params, "maxSpeed", 1, 50).name("Max Speed").step(1);
      gui.add(params, "maxForce", 1, 20).name("Max Force").step(1);
      gui.add(params, "lookAtDirection").name("Look At Direction");
      gui
        .add(params, "inSightDistance", 1000, 10000)
        .name("InSight Distance")
        .step(1);
      gui
        .add(params, "tooCloseDistance", 100, 1000)
        .name("Too Close Distance")
        .step(1);

      window.addEventListener("resize", onWindowResize, false);

      animate();
    }

    function onWindowResize() {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    }

    function animate() {
      requestAnimationFrame(animate);

      for (var i = 0; i < entities.length; i++) {
        entities[i].maxSpeed = params.maxSpeed;
        entities[i].maxForce = params.maxForce;
        entities[i].inSightDistance = params.inSightDistance;
        entities[i].tooCloseDistance = params.tooCloseDistance;
        entities[i].flock(entities);
        if (params.lookAtDirection) entities[i].lookWhereGoing(true);
        else entities[i].rotation.set(0, 0, 0);

        entities[i].update();
        entities[i].bounce(boundaries);
      }
      controls.update();
      renderer.render(scene, camera);
      stats.update();
    }
  </script>

  <body onload="init('container')">
    <div id="container"></div>
    <div id="msg">
      <span style="color: #bfff00; font-weight: bold">FLOCKING:</span
      ><br />Entities Flocking.<br />Try to play with parameters
    </div>
    <a
      href="https://github.com/erosmarcon/three-steer/blob/master/examples/Flocking.html"
      target="_blank"
      ><div class="view-source">View source</div></a
    >
  </body>
</html>
